/* Author: Mark Faust
 *
 * C version of predictor file
*/

#ifndef PREDICTOR_H_SEEN
#define PREDICTOR_H_SEEN

#define TESTMODE	1

#define LOCAL_SIZE		1024
#define GLOBAL_SIZE		4096
#define PC_MASK			0x00000FFC
#define BRANCH_MASK		0x00000FFF 
#define GLOBAL_MASK 		0x00000002
#define LOCAL_MASK		0x00000004
#define CHOICE_MASK		0x00000002
#define LOCAL_HISTORY_MASK	0x03FF

#define LNT_STRONGLY		0x00
#define LNT_LESS_STRONGLY	0x01
#define LNT_LESS_WEAKLY		0x02
#define LNT_WEAKLY		0x03
#define LT_WEAKLY		0x04
#define LT_LESS_WEAKLY		0x05
#define LT_LESS_STRONGLY	0x06
#define LT_STRONGLY		0x07

#define GNT_STRONGLY		0x00
#define GNT_WEAKLY		0x01
#define GT_WEAKLY		0x02
#define GT_STRONGLY		0x03

#define BRANCH_TAKEN		0x01
#define LP_MSB_A_1		0x04
#define GP_MSB_A_1		0x02
#define TAKEN			true
#define NOT_TAKEN		false


#include <cstddef>
#include <cstring>
#include <inttypes.h>
#include <vector>
#include "op_state.h"   // defines op_state_c (architectural state) class 
#include "tread.h"      // defines branch_record_c class

extern int LocalHistory[ LOCAL_SIZE ]; //initialize all elemtns to 0
extern int LocalPrediction[ LOCAL_SIZE ];
extern int GlobalPrediction[ GLOBAL_SIZE ];
extern int GlobalChoice[ GLOBAL_SIZE ];

extern int BranchHistory;
extern int PC;

#ifndef TESTMODE
class PREDICTOR
{
public:
    bool get_prediction(const branch_record_c* br, const op_state_c* os);

    void update_predictor(const branch_record_c* br, const op_state_c* os, bool taken);

};
#endif

#ifdef TESTMODE
	class PREDICTOR
	{
	public:
	    bool get_prediction(const branch_record_c* br);

	    void update_predictor(const branch_record_c* br, bool taken);
	};
#endif

#endif // PREDICTOR_H_SEEN

